#pragma once

#include <iostream>
#include <string>
#include <cstdio>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define EXIT_ERROR(m) \
    do                \
    {                 \
        perror(m);    \
        exit(1);      \
    } while (0)

#define PATH "."
#define PIPE_NAME "fifo"
#define BUFF_SIZE 1024
#define MODE_DEFAULT 0666

class Namedpipe
{
public:
    Namedpipe(const std::string &path, const std::string &name, int mode)
        : _mode(mode)
    {
        _pathname = path + "/" + name;
        // 1.创建命名管道
        int ret = mkfifo(_pathname.c_str(), _mode);
        if (ret < 0)
        {
            EXIT_ERROR("mkfifo");
        }
        printf("mkfifo success!\n");
    }

    ~Namedpipe()
    {
        // 删除命名管道
        std::cout << "~Namedpipe" << std::endl;
        int num = unlink(_pathname.c_str());
        if (num < 0)
        {
            EXIT_ERROR("unlink");
        }
        printf("unlink %s success!\n", _pathname.c_str());
    }

private:
    std::string _pathname;
    int _mode;
};

class FileOper
{
public:
    FileOper(const std::string &path, const std::string &name)
    {
        _pathname = path + "/" + name;
    }

    ~FileOper()
    {
    }

    void OpenForRead()
    {
        // 2.以只读方式打开文件，从文件里读，最后关闭
        _fd = open(_pathname.c_str(), O_RDONLY);
        if (_fd < 0)
        {
            EXIT_ERROR("open for read");
        }
        printf("open for read success!\n");
    }

    void OpenForWrite()
    {
        _fd = open(_pathname.c_str(), O_WRONLY);
        if (_fd < 0)
        {
            EXIT_ERROR("open for write");
        }
        printf("open for write success!\n");
    }

    bool Wait()
    {
        char buff[BUFF_SIZE];
        ssize_t num = read(_fd, buff, BUFF_SIZE - 1);
        if (num > 0)
        {
            std::cout << "wakeup" << std::endl;
            return true;
        }
        else if (num == 0)
        {
            std::cout << "client exit! then server exit!" << std::endl;
        }
        else
        {
            EXIT_ERROR("read");
        }
        return false;
    }

    bool Wakeup()
    {
        char c = 'w';
        ssize_t ret = write(_fd, &c, sizeof(c));
        if (ret < 0)
        {
            EXIT_ERROR("write");
        }
        std::cout << "wakeup" << std::endl;
        return true;
    }

    void Close()
    {
        close(_fd);
        printf("close fd:%d\n", _fd);
    }

private:
    std::string _pathname;
    int _fd;
};